﻿//_______________________________________________________________________________________________________________________
// Copy Right (c) 2010, 2011 SapiensIT Consulting GmbH, all rights reserved
//_______________________________________________________________________________________________________________________
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT
// NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//_______________________________________________________________________________________________________________________
// PROJECT:     sapiens.at.SharePoint (SharePoint 2010/V4)
//_______________________________________________________________________________________________________________________
// VERSION:     2.0
//_______________________________________________________________________________________________________________________
// DESCRIPTION: 
//_______________________________________________________________________________________________________________________
// LICENSE:     Different licens Types apply to different file types:
//               - Source code files are governed by the MICROSOFT PUBLIC LICENSE (Ms-PL)
//               - Binary files are governed by MSDN CODE GALLERY BINARY LICENSE
//               - Documentation files are governed by CREATIVE COMMONS ATTRIBUTION 3.0 LICENSE
//
//               The licenses can be found at the projects source location.
//               If you do not agree, don't use it!
// 
//_______________________________________________________________________________________________________________________
// Start SharePoint Branding, visit http://www.cliggin.com! Visit us on http://www.sapiens.at! Tell your friends! 
//_______________________________________________________________________________________________________________________
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using Microsoft.SharePoint.WebControls;
using System.Web.UI;
using Microsoft.SharePoint;
using Sapiens.at.SharePoint.Extensions;
using Sapiens.at.SharePoint.CustomActions;

namespace Sapiens.at.SharePoint.Controls
{
    /// <summary>
    /// Control that renders all the necessarry javascript to handle custom actions in the ribbon.
    /// </summary>
    public abstract class RibbonScriptLoader : UserControl
    {
        Dictionary<string, IEnumerable<string>> _hiddenForLists;
        /// <summary>
        /// Gets a dictionary that stores a collection of lists that in that context a certain command is not applicable.
        /// </summary>
        protected Dictionary<string, IEnumerable<string>> HiddenForLists
        {
            get
            {
                if (_hiddenForLists == null) { _hiddenForLists = new Dictionary<string, IEnumerable<string>>(); }
                return _hiddenForLists;
            }
        }

        List<RibbonAction> _actions;
        /// <summary>
        /// Gets a collection of the <see cref="RibbonAction"/>s.
        /// </summary>
        IEnumerable<RibbonAction> Actions
        {
            get
            {
                if (_actions == null) { InitRibbonActions(); }
                return _actions;
            }
        }
        
        /// <summary>
        /// Initializes the <see cref="RibbonAction"/>s, by finding all classes in the current assembly.
        /// </summary>
        protected virtual void InitRibbonActions()
        {
            _actions = new List<RibbonAction>();
            foreach (Type type in GetType().Assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(RibbonAction))))
            {
                var action = (RibbonAction)Activator.CreateInstance(type);
                if (action.ApplicableCommands.Count() > 0)
                {
                    _actions.Add(action);
                }
            } 
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            // Catch eventual postbacks
            if (Page.IsPostBack && Request["__EVENTTARGET"].StartsWith("RibbonAction") && Actions.Count() > 0)
            {
                // Call the action(s) for the postbackcommand
                foreach (var action in Actions.Where(a => a.HandlesCommand(Request["__EVENTARGUMENT"])))
                {
                    action.RunCallback(Request["__EVENTARGUMENT"], Page);
                }
            }
        }

        /// <summary>
        /// Collects and renders the javascript
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            var ribbon = SPRibbon.GetCurrent(Page);
            if (ribbon != null && SPContext.Current.List != null)
            {
                foreach (var command in HiddenForLists.Keys.Where(k => HiddenForLists[k].Contains(SPContext.Current.List.RootFolder.Url)))
                {
                    ribbon.TrimById(command);
                }
            }

            if (Actions.Count() > 0)
            {
                foreach (var action in Actions)
                {
                    action.OnPreRender(Page);
                }

                ScriptLink.RegisterScriptAfterUI(Page, "SP.js", false, true);
                ScriptLink.RegisterScriptAfterUI(Page, "CUI.js", false, true);
                ScriptLink.RegisterScriptAfterUI(Page, "/_layouts/Sapiens.at.SharePoint/Ribbon.PageComponent.js", false, true);

                RenderGetGlobalCommands();
                RenderCanHandleCommand();
                RenderHandleCommand();

                ScriptManager.RegisterClientScriptBlock(Page, GetType(), "RibbonStartup", @"
                    function initSapiensRibbon() {
                        Sapiens.at.SharePoint.Ribbon.PageComponent.initialize();
                    }
                    ExecuteOrDelayUntilScriptLoaded(initSapiensRibbon, 'Ribbon.PageComponent.js');
                ", true);

                ScriptManager.RegisterClientScriptBlock(Page, GetType(), "singleItemSelected", @"
                    function singleItemSelected() { 
                        var items = SP.ListOperation.Selection.getSelectedItems(); 
                        var ci = CountDictionary(items); 
                        return (ci == 1); 
                    }

                    function itemsSelected() { 
                        var items = SP.ListOperation.Selection.getSelectedItems(); 
                        var ci = CountDictionary(items); 
                        return (ci >= 1); 
                    }
                ", true);

            }
            base.OnPreRender(e);
        }

        /// <summary>
        /// Builds and renders the javascript function "getGlobalCommands".
        /// </summary>
        protected virtual void RenderGetGlobalCommands()
        {
            // Builds the method that gets called to collect all available commands.

            var sb = new StringBuilder();
            sb.AppendLine("function ribbonControllerGetGlobalCommands(){ ");
            sb.Append("return [");
            foreach (var action in Actions)
            {
                sb.Append(action.GetJSGlobalCommands());
            }

            sb.Remove(sb.Length - 1, 1).AppendLine("];");
            sb.AppendLine("}");
            ScriptManager.RegisterClientScriptBlock(Page, GetType(), "RibbonScriptLoader.getGlobalCommands", sb.ToString(), true);
        }

        /// <summary>
        /// Builds and renders the javascript function "canHandleCommands".
        /// </summary>
        protected virtual void RenderCanHandleCommand()
        {
            // Builds the method that gets called for every custom action to check if it is enabled
            var sb = new StringBuilder();
            sb.AppendLine("function ribbonControllerCanHandleCommand(commandId){");

            foreach (var action in Actions)
            {
                sb.AppendLine(action.GetJSIsEnabled(Page));
            }

            sb.AppendLine("return true;");
            sb.AppendLine("}");
            ScriptManager.RegisterClientScriptBlock(Page, GetType(), "RibbonController.canHandleCommand", sb.ToString(), true);
        }

        /// <summary>
        /// Builds and renders the javascript function "handleCommands".
        /// </summary>
        protected virtual void RenderHandleCommand()
        {
            // Builds the method that gets called when a custom action was clicked
            var sb = new StringBuilder();
            sb.AppendLine("function ribbonControllerHandleCommand(commandId){");

            foreach (var action in Actions)
            {
                sb.AppendLine(action.GetJSCallback());
            }

            sb.AppendLine("}");
            ScriptManager.RegisterClientScriptBlock(Page, GetType(), "RibbonController.handleCommand", sb.ToString(), true);
        }

        public static void RenderStatusBar(Page page, string title, string text, StatusBar.StatusBarColor color)
        {
            ScriptLink.RegisterScriptAfterUI(page, "SP.js", false, true);
            var script = string.Format(@"
                ExecuteOrDelayUntilScriptLoaded(addStatusBar, 'SP.js');
                function addStatusBar(){{
                    var sid = SP.UI.Status.addStatus('{0}', '{1}', true);
                    {2}
                }}
            ", title, text, 
            color != StatusBar.StatusBarColor.None ? string.Format("SP.UI.Status.setStatusPriColor(sid, '{0}');", Enum.GetName(typeof(StatusBar.StatusBarColor), color).ToLower()) : "");

            ScriptManager.RegisterClientScriptBlock(page, typeof(StatusBar), string.Format("StatusBar:{0}", title), script, true);
        }
    }
}
